package com.handle.system.svc.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.handle.common.core.constants.Constant;
import com.handle.common.core.constants.ConstantEnums;
import com.handle.common.core.dto.token.User;
import com.handle.common.core.result.JsonResult;
import com.handle.common.core.utils.ContextHolderUtils;
import com.handle.common.core.utils.PageUtil;
import com.handle.common.redis.generator.RedisIdGenerator;
import com.handle.system.api.constants.ResponseEnum;
import com.handle.system.api.dto.SysRoleDto;
import com.handle.system.api.entity.*;
import com.handle.system.api.request.role.RoleAddOrUpdateParam;
import com.handle.system.api.request.role.RolePermissionParam;
import com.handle.system.api.request.role.RoleQueryParam;
import com.handle.system.api.response.role.Permission;
import com.handle.system.api.response.role.RoleListVo;
import com.handle.system.api.service.ISysRoleService;
import com.handle.system.svc.mapper.SysRoleDeptMapper;
import com.handle.system.svc.mapper.SysRoleMapper;
import com.handle.system.svc.mapper.SysRoleMenuMapper;
import com.handle.system.svc.mapper.SysUserRoleMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统角色表 服务实现类
 * </p>
 *
 * @author zhangqing
 * @since 2021-03-05
 */
@AllArgsConstructor
@Service
@Slf4j
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    private final SysRoleMapper sysRoleMapper;
    private final RedisIdGenerator redisIdGenerator;
    private final SysRoleMenuMapper sysRoleMenuMapper;
    private final SysRoleDeptMapper sysRoleDeptMapper;

    @Override
    public List<SysRole> findRoleByTenantCode(String tenantCode) {
        LambdaQueryWrapper<SysRole> lambda = new QueryWrapper<SysRole>().lambda()
                .eq(SysRole::getStatus, Boolean.TRUE)
                .eq(SysRole::getDelFlag, Boolean.FALSE)
                .eq(SysRole::getTenantCode,tenantCode);
        return this.list(lambda);
    }

    @Override
    public JsonResult roleDetails(Long roleId) {
        LambdaQueryWrapper<SysRole> lambda = new QueryWrapper<SysRole>().lambda()
                .eq(SysRole::getId, roleId);
        SysRole sysRole = sysRoleMapper.selectOne(lambda);
        ResponseEnum.ROLE_NOT_EXISTS.assertIsEmpty(sysRole);
        return JsonResult.success(sysRoleMapper.roleDetails(roleId));
    }

    @Override
    public JsonResult list(RoleQueryParam roleQueryParam) {
        PageUtil.startPageSort(roleQueryParam.getPageNum(), roleQueryParam.getPageSize(),roleQueryParam.getSortField(),roleQueryParam.getSortOrder());
        List<RoleListVo> rolePage = sysRoleMapper.findRolePage(roleQueryParam);
        // 获取全部除了只有超级管理员能读的
        List<Permission> allMenu = sysRoleMapper.findMenu();
        allMenu.forEach(permission-> permission.setActions(new ArrayList<>()));
        // 将全部的菜单转id集合
        List<Long> permissionList=allMenu.stream().map(Permission::getPermissionId).collect(Collectors.toList());
        Optional.ofNullable(rolePage).ifPresent(roleListVos -> roleListVos.forEach(roleListVo -> {
            // 查询角色权限
            List<Permission> rolePermissions = sysRoleMapper.findRolePermissions(roleListVo.getId());
            // 判断查询的角色权限是否为空,如果为空则添加所有权限为空的页面,如不为空取查询到的与全部取差集,然后添加到查询到的
            if(rolePermissions.isEmpty()){
                roleListVo.setPermissions(allMenu);
            }else {
                List<Long> collect = rolePermissions.stream().map(Permission::getPermissionId).collect(Collectors.toList());
                List<Long> differenceIds = permissionList.stream().filter(t -> !collect.contains(t)).collect(Collectors.toList());
                List<Permission> differenceObjects = allMenu.stream().filter(s -> differenceIds.contains(s.getPermissionId())).collect(Collectors.toList());
                rolePermissions.addAll(differenceObjects);
                roleListVo.setPermissions(rolePermissions);
            }
        }));
        return JsonResult.success(PageUtil.restPage(rolePage));
    }

    @Override
    public JsonResult sortList(RoleQueryParam roleQueryParam) {
        LambdaQueryWrapper<SysRole> lambda = new QueryWrapper<SysRole>().lambda()
                .eq(SysRole::getDelFlag, Boolean.FALSE)
                .eq(!StringUtils.isEmpty(roleQueryParam.getStatus()), SysRole::getStatus, roleQueryParam.getStatus())
                .eq(!StringUtils.isEmpty(roleQueryParam.getRoleName()), SysRole::getRoleName, roleQueryParam.getRoleName())
                .eq(!StringUtils.isEmpty(roleQueryParam.getDataScopeType()), SysRole::getDataScope, roleQueryParam.getDataScopeType());
        PageUtil.startPageSort(roleQueryParam.getPageNum(), roleQueryParam.getPageSize(), roleQueryParam.getSortField(), roleQueryParam.getSortOrder());
        List<SysRole> sysRoles = sysRoleMapper.selectList(lambda);
        return JsonResult.success(PageUtil.restPage(sysRoles));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult add(RoleAddOrUpdateParam roleAddOrUpdateParam) {
        log.info("系统服务->角色管理-添加角色->参数: {}", JSONUtil.toJsonStr(roleAddOrUpdateParam));
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(roleAddOrUpdateParam,sysRole);
        Long roleId = redisIdGenerator.nextId(Constant.SYS_ROLE_KEY);
        sysRole.setId(roleId);
        User currentUser = ContextHolderUtils.getCurrentUser();
        sysRole.setCreateStaff(currentUser.getUserId());

        if(ConstantEnums.DataScope.DATA_SCOPE_CUSTOM.getCode().equals(roleAddOrUpdateParam.getDataScope())){
            List<SysRoleDept> sysRoleDepts = new ArrayList<>();
            // 插入sysRoleDept关联表
            roleAddOrUpdateParam.getDeptIds().forEach(deptId->{
                SysRoleDept sysRoleDept = SysRoleDept.builder()
                        .deptId(deptId)
                        .roleId(roleId).build();
                sysRoleDepts.add(sysRoleDept);
            });
            sysRoleDeptMapper.batchAddRoleDept(sysRoleDepts);
        }
        return JsonResult.toJsonResult(sysRoleMapper.insert(sysRole));
    }

    @Override
    public Boolean checkRoleCode(String roleCode,String tenantCode) {
        LambdaQueryWrapper<SysRole> lambda = new QueryWrapper<SysRole>().lambda()
                .eq(SysRole::getRoleCode, roleCode)
                .eq(SysRole::getTenantCode,tenantCode)
                .eq(SysRole::getDelFlag, Boolean.FALSE);
        SysRole sysRole = sysRoleMapper.selectOne(lambda);
        if (StringUtils.isEmpty(sysRole)) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult edit(RoleAddOrUpdateParam roleAddOrUpdateParam) {
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(roleAddOrUpdateParam,sysRole);
        User currentUser = ContextHolderUtils.getCurrentUser();
        sysRole.setUpdateStaff(currentUser.getUserId());
        if(ConstantEnums.DataScope.DATA_SCOPE_CUSTOM.getCode().equals(roleAddOrUpdateParam.getDataScope())){
            LambdaQueryWrapper<SysRoleDept> lambda = new QueryWrapper<SysRoleDept>().lambda()
                    .eq(SysRoleDept::getRoleId, roleAddOrUpdateParam.getId());
            // 删除之前绑定的部门权限
            sysRoleDeptMapper.delete(lambda);
            List<SysRoleDept> sysRoleDepts = new ArrayList<>();
            // 重新插入sysRoleDept关联表
            roleAddOrUpdateParam.getDeptIds().forEach(deptId->{
                SysRoleDept sysRoleDept = SysRoleDept.builder()
                        .deptId(deptId)
                        .roleId(roleAddOrUpdateParam.getId()).build();
                sysRoleDepts.add(sysRoleDept);
            });
            sysRoleDeptMapper.batchAddRoleDept(sysRoleDepts);
        }
        return JsonResult.toJsonResult(sysRoleMapper.updateById(sysRole));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult roleAuthority(SysRoleDto sysRoleDto) {
        LambdaQueryWrapper<SysRoleMenu> lambda = new QueryWrapper<SysRoleMenu>().lambda()
                .eq(SysRoleMenu::getRoleId, sysRoleDto.getId());
        // 先删除原本角色关联的菜单
        sysRoleMenuMapper.delete(lambda);
        // 封装新的角色菜单关联数据
        List<SysRoleMenu> sysRoleMenus = new ArrayList<>();
        sysRoleDto.getMenuIds().forEach(menuId -> {
            SysRoleMenu sysRoleMenu = SysRoleMenu.builder().roleId(sysRoleDto.getId()).menuId(menuId).build();
            sysRoleMenus.add(sysRoleMenu);
        });
        return JsonResult.toJsonResult(sysRoleMenuMapper.batchInsert(sysRoleMenus));
    }

    @Override
    public JsonResult changeRoleStatus(Long id, Boolean status) {
        log.info("系统服务->角色管理->修改角色状态->参数: id:{} status:{}",id,status);
        SysRole sysRole = sysRoleMapper.selectById(id);
        ResponseEnum.ROLE_CODE_EXISTS.assertIsEmpty(sysRole);
        sysRole.setStatus(status);
        return JsonResult.toJsonResult(sysRoleMapper.updateById(sysRole));
    }

    @Override
    public JsonResult batchDelRole(List<Long> ids) {
        log.info("系统服务->角色管理->批量删除角色->参数: ids:{}",ids.toString());
        List<SysRole> sysRoles = sysRoleMapper.selectBatchIds(ids);
        boolean contains = sysRoles.stream().map(SysRole::getRoleCode).collect(Collectors.toList()).contains(Constant.ADMIN);
        if (contains) {
            ResponseEnum.ADMIN_ROLE_NOT_DEL.assertFail();
        }
        return JsonResult.toJsonResult(sysRoleMapper.delRoleByIds(ids));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult permission(RolePermissionParam rolePermissionParam) {
        log.info("系统服务->角色管理->配置角色权限->参数: {}",JSONUtil.toJsonStr(rolePermissionParam));
        // 删除之前保存的角色菜单权限
        sysRoleMenuMapper.delete(new QueryWrapper<SysRoleMenu>()
                .lambda().eq(SysRoleMenu::getRoleId,rolePermissionParam.getId()));
        List<SysRoleMenu> sysRoleMenus = new ArrayList<>();
        // 重新插入
        Optional.ofNullable(rolePermissionParam.getMenuIds()).ifPresent(ids -> ids.forEach(id->{
            SysRoleMenu sysRoleMenu = SysRoleMenu.builder().roleId(rolePermissionParam.getId()).menuId(id).build();
            sysRoleMenus.add(sysRoleMenu);
        }));
        if(!sysRoleMenus.isEmpty()){
            // 批量插入
            sysRoleMenuMapper.batchInsert(sysRoleMenus);
        }
        return JsonResult.success();
    }


}
